/*
 *  Copyright (C) 2004 Cidero, Inc.
 *
 *  Permission is hereby granted to any person obtaining a copy of 
 *  this software to use, copy, modify, merge, publish, and distribute
 *  the software for any non-commercial purpose, subject to the
 *  following conditions:
 *  
 *  The above copyright notice and this permission notice shall be included
 *  in all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
 *  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
 *  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY IN CONNECTION WITH THE SOFTWARE.
 * 
 *  File: $RCSfile: ExternalBrowser.java,v $
 *
 */
package com.cidero.util;

import java.lang.reflect.Method;
import java.io.IOException;
import java.util.logging.Logger;
import java.util.logging.Level;

/**
 * External browser utility class. Allows Java programs to display Web 
 * pages in the system's default browser (or a non-default browser if
 * the user configures the property file to do that)
 *
 * There's a few hoops to jump through in some cases (UNIX mozilla) in
 * order to make this work in cases where there is already an active, open
 * copy of the browser on the system. Need to try one startup option, then
 * an alternate method.
 *
 * Property file syntax:
 *
 *  os1.nameMatch=Windows
 *  os1.primaryExecCmd=cmd.exe /c
 *  os1.alternateExecCmd=
 *
 *  os2.primaryExecCmd=mozilla -P homeDirect
 * 
 */
public class ExternalBrowser
{
  private static Logger logger = Logger.getLogger("com.cidero.util");

  // Used to identify the windows platform.
  private static final String WIN_ID = "Windows";
  // The default system browser under windows.
  private static final String WIN_PATH = "rundll32";
  // The flag to display a url.
  private static final String WIN_FLAG = "url.dll,FileProtocolHandler";
  // The default browser under unix.
  private static final String UNIX_PATH = "mozilla";
  // The flag to display a url.
  private static final String UNIX_FLAG = "-remote openURL";

  String mozillaProfileOptions = "";
  
  /**
   *  Constructs external browser object, using default browser for a 
   *  given system.
   */
  public ExternalBrowser()
  {
  }

  /**
   * Mozilla (and perhaps others) support profile settings. Specify
   * "-P <profile>" here
   */
  public void setMozillaProfileOptions( String profileOptions )
  {
    mozillaProfileOptions = profileOptions;
  }
  
  public void displayURL( String url )
  {
    String cmd = null;
    try
    {
      if( isWindowsPlatform() )
      {
        // Old method - probably works but may go away, I'm thinkin...
        // cmd = 'rundll32 url.dll,FileProtocolHandler http://...'
        //        cmd = WIN_PATH + " " + WIN_FLAG + " " + url;

        // New method - use start command. Start is not external command
        // so need to run cmd.exe shell 
        cmd = "cmd.exe /c start " + url;

        //System.out.println("cmd = " + cmd );
        Process p = Runtime.getRuntime().exec(cmd);
      }
      else if( isMacOSXPlatform() )
      {
        try
        {
          Class mrjFileUtilsClass = Class.forName(
                              "com.apple.mrj.MRJFileUtils");
          Method openURL = mrjFileUtilsClass.getDeclaredMethod("openURL",
                          new Class[] {String.class});

          openURL.invoke(null, new Object[] { url });
        }
        catch (Exception e)
        {
          logger.warning("Error bringing up browser, exception = " +
                         e.toString() );
        }
      }
      else
      {
        // Under Unix, Mozilla has to be running for the "-remote"
        // command to work.  So, we try sending the command and
        // check for an exit value.  If the exit command is 0,
        // it worked, otherwise we need to start the browser.
        // cmd = 'netscape -remote openURL(http://www.javaworld.com)'
        cmd = UNIX_PATH + " " + mozillaProfileOptions + " " + 
              UNIX_FLAG + "(" + url + ")";

        //System.out.println("cmd = " + cmd );

        Process p = Runtime.getRuntime().exec( cmd );
        try
        {
          // wait for exit code -- if it's 0, command worked,
          // otherwise we need to start the browser up.
          int exitCode = p.waitFor();
          if (exitCode != 0)
          {
            // Command failed, start up the browser
            // cmd = 'netscape http://www.javaworld.com'
            cmd = UNIX_PATH + " "  + mozillaProfileOptions + " " + url;
            p = Runtime.getRuntime().exec( cmd );
          }
        }
        catch(InterruptedException e)
        {
          logger.warning("Error bringing up browser, cmd='" +
                         cmd + "'");
          logger.warning("Caught: " + e);
        }
      }
    }
    catch(IOException e)
    {
      // couldn't exec browser
      logger.warning("Could not invoke browser, command=" + cmd);
      logger.warning("Caught: " + e);
    }
  }

  /**
   * Try to determine whether this application is running under Windows
   * or some other platform by examing the "os.name" property.
   *
   * @return true if this application is running under a Windows OS
   */
  public static boolean isWindowsPlatform()
  {
    String os = System.getProperty("os.name");
    //System.out.println("os = " + os );
    if ( os != null && os.startsWith(WIN_ID))
      return true;
    else
      return false;
  }

  public static boolean isMacOSXPlatform()
  {
    String os = System.getProperty("os.name");
    //logger.fine("OS = " + os );
    if( os.toLowerCase().indexOf("os x") >= 0 )
      return true;

    return false;
  }

  /**
   * Simple test
   */
  public static void main( String args[] )
  {
    String url = "http://www.cidero.com";

    ExternalBrowser browser = new ExternalBrowser();
    browser.setMozillaProfileOptions("-P homeDirect");
    browser.displayURL( url );
  }
}
